package com.example.util.service;


import javax.net.ssl.HostnameVerifier;

import com.example.util.model.Response;
import com.example.util.util.FileUtil;
import com.example.util.util.GetColumns;
import com.example.util.util.HttpTemplate;
import com.example.util.util.SHA256;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.dom4j.Document;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import org.dom4j.Element;
import org.dom4j.DocumentHelper;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.dom4j.io.XMLWriter;
import org.springframework.util.StringUtils;


@Slf4j
public class TerminalManageServiceImpl {


    private static int socketTimeout = 30000;

    private static int connectTimeout = 30000;

    private static int evictTimeout = 30000;

    private static int connectMaxTotal = 10;

    private static int connectMaxConnPerRoute = 10;

    private static String chatbotKey = "C21021000003";

    private static String chatbotToken = "63f564d57b3df1ab4eb27bb1011b828bc3a6d6846d6cf37914f46c95dc6ba816";

    private static String terminalManageUrl = "https://hdn-csp-cgw.cmicmaap.com/ue/v1/capability/5gmsg/sip:106505110000195559@botplatform.rcs.chinamobile.com";
//    private static String terminalManageUrl = "http://10.10.183.121:16302/ue/v1/capability/5gmsg/sip:106505110000195559@botplatform.rcs.chinamobile.com";
//    private static String terminalManageUrl = "http://36.133.49.173:2999/ue/v1/capability/5gmsg/sip:106505110000195559@botplatform.rcs.chinamobile.com";


    public static List queryTerminalManage(List<String> mobiles, String url) {

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout)
                .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();
        HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig);
        builder.evictExpiredConnections().evictIdleConnections(evictTimeout, TimeUnit.MILLISECONDS);
        builder.setMaxConnTotal(connectMaxTotal).setMaxConnPerRoute(connectMaxConnPerRoute);
        try {

            builder.setSSLSocketFactory(createSSLConnSocketFactory());
        } catch (Exception e) {
            log.error("创建HttpClient异常", e);
        }
        final CloseableHttpClient httpClient = builder.build();


        final String gmtDate = GetColumns.getGMTDate();

        String authorization;
        authorization = chatbotKey + ":" + SHA256.getSHA256(chatbotToken + gmtDate);
        authorization = "Basic " + Base64.getUrlEncoder().encodeToString(authorization.getBytes());
        HttpPost httpPost = null;
        if (url != null) {
            httpPost = new HttpPost(url);
        } else {
            httpPost = new HttpPost(TerminalManageServiceImpl.terminalManageUrl);
        }
        httpPost.setHeader("Authorization", authorization);
        httpPost.setHeader("date", gmtDate);

        String terminalManagePhones = getTerminalManagePhones(mobiles);

        if (log.isDebugEnabled()) {
            log.debug("终端能力查询接口请求参数:{}", terminalManagePhones);
        }
        StringEntity stringEntity = new StringEntity(terminalManagePhones, ContentType.APPLICATION_XML.withCharset("utf-8"));
        httpPost.setEntity(stringEntity);
        CloseableHttpResponse response = null;
        List<String> result = new ArrayList<>();

        try {
            response = httpClient.execute(httpPost);

            if (null == response) {
                log.error("queryTerminalManage, maap平台响应数据为空");
                return result;
            }


            HttpEntity entity = response.getEntity();
            String responseString = EntityUtils.toString(response.getEntity(), "UTF-8");
            if (log.isDebugEnabled()) {
                log.debug("statusCode: {}, responseString: {}", response.getStatusLine().getStatusCode(), responseString);
            }
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

                try {
                    Document reqDoc;
                    SAXReader reader = new SAXReader();
                    reader.setEncoding("utf-8");
                    reqDoc = reader.read(new StringReader(responseString));
                    Element reqRoot = reqDoc.getRootElement();
                    final Iterator iterator = reqRoot.elementIterator("address");
                    if (null == iterator) {
                    }
                    while (iterator.hasNext()) {
                        Element element1 = (Element) iterator.next();
                        final String stringValue = element1.getStringValue().replace("+86", "");
                        result.add(stringValue);
                    }
                } catch (Exception e) {
                    log.error("单条读取XML异常_" + e.getMessage(), e);
                }
                return result;
            }
        } catch (Exception e) {
            log.error("调用maap平台出现异常_" + e.getMessage(), e);
            return result;
        } finally {
            if (null != response) {
                try {
                    response.close();
                } catch (IOException ie) {
                    log.error("关流异常_" + ie.getMessage(), ie);
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException ie) {
                    log.error("关流异常_" + ie.getMessage(), ie);
                }
            }
        }
        return result;
    }

    public static List queryTerminalManageV2(List<String> mobiles, String url, String chatbotToken) {
        HttpTemplate httpTemplate = HttpTemplate.initSingleton();
        String terminalManagePhones = getTerminalManagePhones(mobiles);
        Response response = httpTemplate.executeXml(url, terminalManagePhones, chatbotToken);
        List<String> result = new ArrayList<>();
        if (null == response) {
            log.error("queryTerminalManage, maap平台响应数据为空");
            return result;
        }
        String responseString = response.getResponseBody();
        log.info("=========================请求运营商响应码:{}", response.getResponseCode());
        if (log.isDebugEnabled()) {
            log.debug("statusCode: {}, responseString: {}", response.getResponseCode(), responseString);
        }
        if (response.getResponseCode().intValue() == HttpStatus.SC_OK && response.getResponseBody() != null) {

            try {
                Document reqDoc;
                SAXReader reader = new SAXReader();
                reader.setEncoding("utf-8");
                reqDoc = reader.read(new StringReader(responseString));
                Element reqRoot = reqDoc.getRootElement();
                final Iterator iterator = reqRoot.elementIterator("address");
                if (null == iterator) {
                }
                while (iterator.hasNext()) {
                    Element element1 = (Element) iterator.next();
                    final String stringValue = element1.getStringValue().replace("+86", "");
                    result.add(stringValue);
                }
            } catch (Exception e) {
                log.error("单条读取XML异常_" + e.getMessage(), e);
            }
        } else {
            return null;
        }
//        if (response.getResponseCode().intValue() == HttpStatus.SC_BAD_REQUEST && response.getRequestBody() != null) {
//            //存储错误内容
//            String requestBody = response.getRequestBody();
//            FileUtil.put2File(requestBody, "/opt/app/rms_fg/util-white/error");
//        }
        return result;
    }

    public static String getTerminalManagePhones(List<String> mobiles) {
        Document document = DocumentHelper.createDocument();
        Element queryList = document.addElement("queryList");
        for (String mobile : mobiles) {
            if (!StringUtils.isEmpty(mobile) && Pattern.matches("\\d{11}", mobile)) {
                queryList.addElement("address").addText("+86" + mobile);
            }
        }
        return asXML(document, "utf-8", false);
    }

    private static SSLConnectionSocketFactory createSSLConnSocketFactory() throws GeneralSecurityException {
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) {
                return true;
            }
        }).build();
        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
        return new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
    }

    public static String getSHA256(String str) {
        MessageDigest messageDigest;
        String encodestr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            encodestr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            log.error("sha256加密出现异常", e);
        } catch (UnsupportedEncodingException e) {
            log.error("sha256加密出现异常", e);
        }
        return encodestr;
    }

    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
                //1得到一位的进行补0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }

    public static String asXML(Document doc, String encoding, boolean escapeText) {
        OutputFormat format = new OutputFormat();
        format.setEncoding(encoding);
        StringWriter out = null;
        XMLWriter writer = null;
        try {
            out = new StringWriter();
            writer = new XMLWriter(out, format);
            writer.setEscapeText(escapeText);
            writer.write(doc);
            writer.flush();
            return out.toString();
        } catch (IOException e) {
            log.error("读取xml异常", e);
        } finally {
            try {
                if (null != out) {
                    out.close();
                }
                if (null != writer) {
                    writer.close();
                }
            } catch (IOException i) {
                log.error("关流异常", i);
            }
        }
        return null;
    }
}
